/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * Description: Hmfs-tools mkfs format
 */

#ifndef MKFS_FORMAT_H
#define MKFS_FORMAT_H

#include <memory>
#include <string>
#include <sys/types.h>

#include "hmfs_command.h"
#include "hmfs_fs.h"
#include "hmfs_zoned.h"
#include "super_block_writer.h"

namespace OHOS {
namespace Hmfs {
struct HmfsData {
    uint32_t sectorSize = 0;
    uint32_t sectorsPerBlk = DEFAULT_SECTORS_PER_BLOCK;
    uint32_t segsPerZone = 1;
    uint64_t sectorCount = 0;
    size_t blocksPerZone = 0;
    uint64_t zoneAlignStartOffset = 0;
    uint32_t segment0BlockId = 0;
    uint32_t segmentCount = 0;
    uint32_t zoneAlignedSegCount = 0;
    uint32_t segmentCountInCP = HMFS_CP_COUNT;
    uint32_t sitStartBlkId = 0;
    uint32_t segmentCountInSIT = 0;
    uint32_t natStartBlkId = 0;
    uint32_t segmentCountInNAT = 0;
    uint32_t checkPointPayload = 0;
    uint32_t segmentCountInSSA = 0;
    uint32_t mainStartBlkId = 0;
    uint32_t sectionCount = 0;
    uint32_t segmentCountInMain = 0;
    uint32_t reservedSegments = 0;
    uint32_t nodeInode = 1;
    uint32_t metaInode = 2;
    uint32_t rootInode = 3;
    uint32_t nextFreeInodeId = 4;
    uint32_t quotaInodeCount = 0;
    uint32_t quotaDataBlks = 0;
    uint32_t lpfInodeId = 0;
    uint32_t lpfInodeCount = 0;
    uint32_t lpfDataBlks = 0;
    uint32_t checksumSeed = 0;
    int32_t zonedModel = HMFS_ZONED_NONE;
    char version[VERSION_TOTAL_LEN + 1];
    uint32_t currentSegments[CURSEG_TYPE_MAX];
};

class MkfsFormat {
public:
    MkfsFormat(CmdConfig &cfgPara);
    ~MkfsFormat() = default;
    int32_t Process();

private:
    friend class CheckPointWriter;
    friend class MainAreaWriter;
    friend class NatWriter;
    friend class SitWriter;
    friend class SuperBlockWriter;

    CmdConfig &cfgPara_;
    HmfsData hmfsData_;
    std::unique_ptr<SuperBlockWriter> superBlockFormater_ = nullptr;

    inline uint32_t PreviousZone(uint32_t curSegType)
    {
        return hmfsData_.currentSegments[curSegType] - hmfsData_.segsPerZone;
    }

    inline uint32_t NextZone(uint32_t curSegType)
    {
        return hmfsData_.currentSegments[curSegType] + hmfsData_.segsPerZone;
    }

    inline uint32_t LastZone(uint32_t zoneCount)
    {
        return (zoneCount - 1) * hmfsData_.segsPerZone;
    }

    inline uint32_t LastSection(uint32_t zoneId)
    {
        return zoneId + (cfgPara_.sectionsPerZone - 1) * cfgPara_.segsPerSection;
    }

    int32_t Format();
    void ClacBlockSize();
    bool DealZoneModel();
    int32_t CalcHmfsDataEnd();
    int32_t CalcHmfsData();
    void VerifyCurSegData(void);
    int32_t CreateDeviceInfo();
    void CreateFormaters();
    int32_t GetDeviceSectorInfo();
    SuperBlockData *GetSuperBlockData();
    int32_t OverwriteDevices();
    int32_t GetZoneInfo();
    int32_t CheckDevicesMounted();
};

} // namespace Hmfs
} // namespace OHOS
#endif // MKFS_FORMAT_H
